﻿namespace FML

#light
     


#if INTERACTIVE
#I @"C:\Program Files\Reference Assemblies\Microsoft\F#\1.0\Runtime\v2.0"
#I @"C:\Windows\Microsoft.NET\Framework\v2.0.50727"
#I @"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5"

#r "mscorlib.dll"
#r "System.dll"
#r "System.Core.dll"
#r "C:\Users\jcm\Documents\projects\Monads\libs\FsCheck.dll"
#r "C:\Users\jcm\Documents\projects\Monads\libs\NunitCore.dll"
#r "C:\Users\jcm\Documents\projects\FML\FML\obj\Debug\Monads.dll"
#endif

module ListT =

 printf "list trans test\n\n"

 module Option = 

  open ListT.Option

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck

  let (>>=) m f = listOptionT.Bind (m, f)
  let ret = listOptionT.Return
 
  quickCheck (fun  f a -> ((ret a) >>= f) = f a)
  quickCheck (fun m  -> (m >>= ret) = m)
  quickCheck (fun m f g-> ((m >>= f) >>= g) = (m >>= (fun x -> f x >>= g)))

  
 module State =

  open ListT.State
  open StateM

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck

  let (>>=) m f = listStateT.Bind (m, f)
  let ret = listStateT.Return
 
  quickCheck (fun f a s-> run ((ret a) >>= f) s = run (f a) s)
  quickCheck (fun m s -> run (m >>= ret) s = run m s)
  quickCheck (fun m f' g' s -> let f x = ret (f' x)
                               let g x = ret (g' x)
                               run  ((m >>= f) >>= g) s = run (m >>= (fun x -> f x >>= g)) s)


                               
 module Error =

  open ListT.Error
  open ErrorM

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck

  let (>>=) m f = listErrorT.Bind (m, f)
  let ret = listErrorT.Return
 
  quickCheck (fun f a ->  ((ret a) >>= f)  =  (f a) )
  quickCheck (fun m  ->  (m >>= ret)  =  m )
  quickCheck (fun m f' g'  -> let f x = ret (f' x)
                              let g x = ret (g' x)
                              ((m >>= f) >>= g)  =  (m >>= (fun x -> f x >>= g)) )


 module Reader =

  open ListT.Reader
  open ReaderM

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck

  let (>>=) m f = listReaderT.Bind (m, f)
  let ret = listReaderT.Return
 
  quickCheck (fun f a s -> run ((ret a) >>= f) s  = run  (f a) s )
  quickCheck (fun m s ->  run (m >>= ret) s =  run m s)
  quickCheck (fun m f' g' s -> let f x = ret (f' x)
                               let g x = ret (g' x)
                               run ((m >>= f) >>= g)  s =  run (m >>= (fun x -> f x >>= g)) s)

 module Writer =

  open ListT.Writer
  open WriterM
  open Monoid

  open  Microsoft.FSharp.Control
  open  Microsoft.FSharp.Control.LazyExtensions
  open FsCheck
  
  let monoid = new ListMonoid<int>() :> Monoid<int list>

  let writerM = WriterBuilder<int list>(monoid) :> IWriterMonad<int list>

  let listWriterT = new ListWriterBuilder<int list>(writerM) :> IListWriterTrans<int list>

  let (>>=) m f = listWriterT.Bind (m, f)
  let ret = listWriterT.Return
 
  quickCheck (fun f a ->  ((ret a) >>= f)   =   (f a)  )
  quickCheck (fun m ->   (m >>= ret)  =   m )
  quickCheck (fun m f' g'   -> let f x = ret (f' x)
                               let g x = ret (g' x)
                               ((m >>= f) >>= g)   =   (m >>= (fun x -> f x >>= g)) )
